/***************************************************************************
 *   Copyright (C) 2008 by András Bécsi                                    *
 *   andrewbecsi @ yahoo . co . uk                                         *
 *                                                                         *
 *   This header file is part of the Qtdict project.                       *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#ifndef UTILS_H
#define UTILS_H

#include "languages.h"


#define ONLINE true

//
typedef QPair<QString, QString> StringPair;
typedef QList< StringPair > StrPairList;
typedef QPair< QStringList,QStringList > StrListPair;
typedef QSet< StringPair > StrPairSet;
typedef QPair<QString, StrPairList > Result;
typedef QList< Result > ResultList;

typedef QPair<Lang, Lang> LangPair;
typedef QList<Lang> LangList;
typedef QList<LangPair> LangPairList;
typedef QHash<LangPair, StrPairList> QueryHash;
typedef QHash<LangPair, QString> LangHash;
typedef QHashIterator<LangPair, QString> LangHashIterator;

static Languages lngConv; // helper class from languages.h

namespace utils {

inline QStringList& sort(QStringList& list) {
    qSort(list.begin(), list.end());
    return list;
}


inline StrPairList unite( const StrPairList& list, const StrPairList& other ) {
    qDebug() << "In function "+QString(Q_FUNC_INFO);
    StrPairSet  set = list.toSet();
    set.unite( other.toSet() );
    StrPairList unique( set.toList() );
    qSort(unique.begin(), unique.end());

    return list;
}

//! return a pair of stringlists converted from &lst
inline StrListPair toStrListPair( const  StrPairList &lst ) {
    qDebug() << "In function "+QString(Q_FUNC_INFO);
    QStringList fi;
    QStringList se;

    for (int i = 0; i < lst.size(); ++i) {
        fi << lst[i].first ;
        se << lst[i].second ;
    }
    StrListPair pair = qMakePair( fi, se);
    return pair;

}


//! return a list of stringpairs created from &f and &s
inline StrPairList toStrPairList(const  QStringList &f, const QStringList &s ) {
    qDebug() << "In function "+QString(Q_FUNC_INFO);
    if ( f.size() != s.size() ) {
        qDebug() << "ERROR in function "+QString(Q_FUNC_INFO)+": f.size() != s.size(). You may loose data, or returned list may be garbage!";
        qDebug(">>>>>>>>>>");
        qDebug()<<"F: "<<f.size();
        qDebug("----------");
        qDebug()<<"S: "<<s.size();
        qDebug("<<<<<<<<<<");
    }

    int size=( f.size() > s.size() ) ? s.size() : f.size();
    StrPairList ret;
    for ( int i=0; i < size; i++ ) {
        ret << qMakePair( f[i], s[i] );
    }
    return ret;
}

//! split second element of &compact list items into substrings using separator &sep
inline StrPairList extract(const StrPairList &compact, const QString &sep ) {
    qDebug() << "In function "+QString(Q_FUNC_INFO);
    StrPairList lst;
    for (int i = 0; i < compact.size(); ++i) {
        QStringList tmp = compact[i].second.split( sep, QString::SkipEmptyParts );
        for (int j = 0; j < tmp.size(); ++j) {
            lst << qMakePair( compact[i].first, tmp[j] );
        }
    }

    return lst;
}

//! join second elements of &large list items into a single string if first elements are equal, using separator &sep
inline StrPairList compress( const StrPairList &large, const QString &sep ) {
    qDebug() << "In function "+QString(Q_FUNC_INFO);
    StrPairList lst;
    QStringList tmp;
    if (!large.isEmpty()) {
        lst << qMakePair( large[0].first, QString("") );
        tmp << large[0].second;

        for (int i = 1; i < large.size(); ++i) {
            QString last("");
            if (!tmp.isEmpty()) last = tmp.last();
            if ( (large[i].first == lst.last().first) ) {
                if ( large[i].second != last ) tmp << large[i].second;
            } else {
                lst.last().second = tmp.join(sep);
                tmp.clear();
                tmp << large[i].second;
                lst << qMakePair( large[i].first, QString("") );
            }
        }
        lst.last().second = tmp.join(sep);
    }
    return lst;
}

//! filter from &text using &rx
inline QStringList filter(const QString &text, QRegExp &rx ) {
    qDebug() << "In function "+QString(Q_FUNC_INFO);
    QStringList list;
    QString str;
    int pos = 0;
    while ((pos = rx.indexIn(text, pos)) != -1) {
        str = rx.cap(1);
        list.append(str);
//qDebug()<<"rx.cap(): "<< str;
        pos += rx.matchedLength();
    }

    return list;
}



//! return a list of pairs of strings specified by &frx and &srx filtered from &text
inline StrPairList parse(const QString &text, QRegExp &frx, QRegExp &srx ) {
    qDebug() << "In function "+QString(Q_FUNC_INFO);
    QStringList fMatch;
    QStringList sMatch;
//qDebug()<<text;
    fMatch = filter( text, frx );
    sMatch = filter( text, srx );

    qDebug()<<"frx: "<<frx.pattern();
    qDebug()<<"srx: "<<srx.pattern();
    qDebug()<<"fMatchSize: "<< fMatch.size();
    qDebug()<<"sMatchSize: "<< sMatch.size();

    return toStrPairList( fMatch, sMatch );
}


//! replace every occurence of &rep_list keys in &text, to &rep_list values
inline QString replace( const QString &text, StrPairList &rep_list ) {
    qDebug() << "In function "+QString(Q_FUNC_INFO) ;

    QString tmp(text);

    for (int i = 0; i < rep_list.size(); ++i) {
        tmp.replace(rep_list[i].first,rep_list[i].second);
    }
    return tmp;
}

//! replace all occurences of &rep_list keys in &list items, to &rep_list values
inline QStringList replace( const QStringList &list, StrPairList &rep_list ) {
    qDebug() << "In function "+QString(Q_FUNC_INFO) << " LIST";
    QStringList tmp(list);
    for (int i = 0; i < list.size(); ++i) {
        tmp[i]=replace(tmp[i], rep_list);
    }
    return tmp;
}


//! removes every occurrence of the regular expression &rx in the string &text
inline QString remove( const QString &text, QRegExp &rx ) {
    qDebug() << "In function "+QString(Q_FUNC_INFO);
    QString tmp(text);
    tmp.remove(rx);
    return tmp;
}

//! removes every occurrence of the regular expressions in &rx_list in the string &text
inline QString remove(const QString &text, QList< QRegExp > &rx_list ) {
    qDebug() << "In function "+QString(Q_FUNC_INFO);
    QString tmp(text);
    QRegExp rx;
    foreach(rx,rx_list) {
        tmp = remove(tmp, rx);
    }
    return tmp;
}

//! print &lst pair list to debug output
inline void debug (const StrPairList &lst) {
    qDebug() << "In function "+QString(Q_FUNC_INFO);
    StringPair pair;
    foreach(pair, lst) {
        qDebug() << pair;
    }
}

}

#endif //UTILS_H

